package main

// this is a simple demo for client-go out of cluster
import (
	"context"
	"flag"
	"fmt"
	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/tools/clientcmd"
	"k8s.io/client-go/util/homedir"
	"path/filepath"
)

func main() {
	// find the kubeconfig file
	// 声明一个字符串指针变量kubeconfig，用于存储kubeconfig文件路径
	var kubeconfig *string

	// 获取用户家目录路径，如果存在家目录
	if home := homedir.HomeDir(); home != "" {
		// 定义命令行字符串参数的一个函数 为程序添加一个命令行参数
		// 定义命令行标志--kubeconfig，默认值为家目录下的.kube/config文件
		// 参数说明：
		// 1. "kubeconfig" - 命令行参数名称
		// 2. filepath.Join(home, ".kube", "config") - 默认路径
		// 3. "(optional)..." - 参数帮助信息（描述信息），说明这是可选的绝对路径
		// 返回值：
		// 返回一个指向字符串的指针（*string）
		// 例如：
		// 1. --kubeconfig=/path/to/kubeconfig
		// 2. --kubeconfig=~/.kube/config
		// 3. --kubeconfig=.kube/config
		kubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file")
	} else {
		// 如果没有家目录，则设置默认值为空字符串
		kubeconfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file")
	}
	// 在程序运行时 解析用户输入的命令行参数
	// 此命令会解析程序启动时传入的命令行参数，并将值赋给之前定义的flag变量
	// 例如：--kubeconfig=/path/to/kubeconfig
	// 如果没有指定参数，则使用flag.String等函数中定义的默认值
	flag.Parse()

	// 使用clientcmd包从kubeconfig文件构建Kubernetes客户端配置
	// 参数说明：
	// 1. "" - masterURL参数，这里为空表示使用kubeconfig中的配置
	// 2. *kubeconfig - kubeconfig文件路径，从命令行参数获取
	// 返回值：
	// 1. config - 成功时返回的Kubernetes客户端配置
	// 2. err - 错误信息，如果构建配置失败则返回错误
	config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
	if err != nil {
		// 如果构建配置失败，直接panic终止程序并输出错误信息
		panic(err.Error())
	}

	// 使用clientcmd包从Kubernetes客户端配置构建Kubernetes客户端
	// 参数说明：
	// 1. config - 成功时返回的Kubernetes客户端配置
	// 返回值：
	// 1. clientSet - 成功时返回的Kubernetes客户端
	// 2. err - 错误信息，如果构建客户端失败则返回错误
	// 3. 如果构建客户端失败，直接panic终止程序并输出错误信息
	clientSet, err := kubernetes.NewForConfig(config)
	if err != nil {
		panic(err.Error())
	}

	// 使用Kubernetes客户端获取所有Node节点的列表
	// 参数说明：
	// 1. context.TODO() - 使用空的上下文，表示没有超时或取消控制
	// 2. v1.ListOptions{} - 空的列表选项，表示获取所有节点
	// 返回值：
	// 1. list - 成功时返回的节点列表
	// 2. err - 错误信息，如果获取列表失败则返回错误
	list, err := clientSet.CoreV1().Nodes().List(context.TODO(), v1.ListOptions{})
	if err != nil {
		// 如果获取节点列表失败，打印错误信息到标准输出
		fmt.Println(err)
	}
	// 打印所有的Node节点的列表
	for _, item := range list.Items {
		fmt.Println(item.Name)
	}

}
